import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Polygon;
import java.awt.Stroke;
import java.awt.geom.Path2D;
import java.awt.geom.Rectangle2D;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

/** BridgeIcon Class :D
    CS158A Spring 2010 Project #2
    @author Clare Lanam and Loc Phan
    */

public class BridgeIcon
{
   /** the bridge represented by this icon */
   private Bridge bridge;
   
   // ------[GENERIC GRAPHICS DATA]------ //
   
   /** whether or not the icon is selected */
   private boolean isSelected;
   /** graphics path to store bridge's shape */
   private Path2D path;
   /** buffer rectangle -- don't let icons get too close! */
   private Rectangle2D.Float bufferRect;
   
   // ------[COORDINATE STUFF]------ //
   
   /** x-coordinate of center point */
   private int x;
   /** y-coordinate of center point */
   private int y;
   /** height of the icon */
   private static final int HEIGHT = 30;
   /** width of the icon */
   private static final int WIDTH = 50;
   /** width of buffer space */
   private static final int BUFFER = 30;
   
   // ------[COLOR & FONT CONSTANTS]------ //
   
   /** dark root color */
   public static final Color ROOT_DARK = new Color(70, 180, 50); 
   /** light root color */
   public static final Color ROOT_LIGHT = new Color(180, 250, 150);
   /** dark regular bridge color */
   public static final Color BRIDGE_DARK = new Color(70, 70, 180);
   /** light regular bridge color */
   public static final Color BRIDGE_LIGHT = new Color(180, 180, 250);
   /** bridge ID font */
   public static final Font ID_FONT = new Font("Arial", Font.PLAIN, 10);
   
   // ------[FUN STUFF]------ //
   
   /** alpha value for transparency <3 */
   private int alpha = 255;
   
   // ------[CONSTRUCTOR]------ //
   
   /** Default constructor sets location of bridge
       @param b bridge that this icon represents
       @param x x-coordinate of center of icon
       @param y y-coordinate of center of icon
       */
   
   public BridgeIcon(Bridge b, int x, int y)
   {
      this.x = x;
      this.y = y;
      
      bridge = b;
      initializeShape();
      isSelected = false;
   }
   
   // ------[PUBLIC METHODS]------ //
   
   /** Returns whether point (x, y) intrudes on the bridge
       icon's personal space. */
   
   public boolean bufferSpaceContains(int x, int y)
   {
      if (path == null)
         return false;
      
      x = x - this.x;
      y = y - this.y;
      return bufferRect.contains(x, y);
   }
   
   /** Returns whether point (x, y) is contained by the icon. */
   
   public boolean contains(int x, int y)
   {
      if (path == null)
         return false;
      
      x = x - this.x;
      y = y - this.y;
      return path.contains(x, y);
   }

   /** Handles bridge icon paint! XD
       @param c the component
       @param g the graphics context
       @param x the x-location
       @param y the y-location
       */
   
   public void draw(Graphics2D g2)
   {
      if (path == null)
         return;
      
      // ------:Setting the colors appropriately:------ 
      
      Color line = BRIDGE_DARK;
      Color fill = BRIDGE_LIGHT;
      Stroke stroke = new BasicStroke(1);
      
      if (bridge.isRoot())
      {
         line = ROOT_DARK;
         fill = ROOT_LIGHT;
      }
      
      if (isSelected)
      {
         Color temp = line;
         line = fill;
         fill = temp;
         stroke = new BasicStroke(2);
      }
      
      // ------:transparency:------
      
      int a = alpha;
      if (bridge.DISABLED)
         a = (a*2)/3;
      
      line = new Color(line.getRed(), line.getGreen(),
            line.getBlue(), a);
      fill = new Color(fill.getRed(), fill.getGreen(),
            fill.getBlue(), a);
      
      // ------:ID tag placement:------
      
      g2.setFont(ID_FONT);
      FontMetrics fm = g2.getFontMetrics();
      Rectangle2D strRect = fm.getStringBounds(bridge.getID(), g2);
      int strX = (int)(-(strRect.getWidth()/2) - 0.01);
      int strY = (int)(HEIGHT/4 -(strRect.getHeight()/2)
            + fm.getAscent() + 0.01);
      
      // ------:Just draw it:------
      
      g2.translate(x, y);
      g2.setColor(fill);
      g2.fill(path);
      g2.setColor(line);
      g2.setStroke(stroke);
      g2.draw(path);
      g2.drawString(bridge.getID(), strX, strY);
      g2.translate(-x, -y);
   }
   
   /** Returns the alpha value. */
   public int getAlpha() { return alpha; }
   
   /** Returns the bridge associated with this bridge icon. */
   public Bridge getBridge() { return bridge; }
   
   /** Returns the ID of the bridge. */
   public String getID() { return bridge.getID(); }
   
   /** Returns the x-coordinate of the icon's center. */
   public int getX() { return x; }
   
   /** Returns the y-coordinate of the icon's center. */
   public int getY() { return y; }
   
   /** Adds a value to transparency alpha. Caps btwn 255 and 0. */
   
   public void incrementAlpha(int inc)
   {
      alpha += inc;
      
      if (alpha > 255)
         alpha = 255;
      if (alpha < 0)
         alpha = 0;
   }
   
   /** Determines whether this bridge icon has a particular bridge ID */
   
   public boolean matches(String bridgeID)
   {
      return (bridge.getID().compareTo(bridgeID) == 0);
   }
   
   /** Reads a bridge from a file. */
   
   public static BridgeIcon read(ObjectInputStream in)
         throws IOException, ClassNotFoundException
   {
      int x = in.readInt();
      int y = in.readInt();
      String id = (String)in.readObject();
      return new BridgeIcon(new Bridge(id), x, y);
   }
   
   /** Set whether or not the bridge icon is selected.
       @param isSelected is the icon selected? you get to pick!
       */
   
   public void setSelected(boolean isSelected)
   {
      this.isSelected = isSelected;
   }
   
   /** Writes this bridge icon object to a file.
       Does not save state (rootID, etc) of contained bridge.
       */
   
   public void write(ObjectOutputStream out) throws IOException
   {
      out.writeInt(x);
      out.writeInt(y);
      out.writeObject(bridge.getID());
   }
   
   // ------[PRIVATE HELPER METHODS]------ //
   
   /** Initialize the bridge shape. */
   
   private void initializeShape()
   {
      path = new Path2D.Float();
      
      // Chapter 1
      // In which Clare gets to draw a hat! :D
      
      int left = 0 - WIDTH/2;
      int top  = 0 - HEIGHT/2;
      
      Point[] points = new Point[8];
      points[0] = new Point(left, 0);
      points[1] = new Point(left + WIDTH/4, 0);
      points[2] = new Point(left + WIDTH/4, top);
      points[3] = new Point(left + 3*WIDTH/4, top);
      points[4] = new Point(left + 3*WIDTH/4, 0);
      points[5] = new Point(left + WIDTH, 0);
      points[6] = new Point(left + WIDTH, -top);
      points[7] = new Point(left, -top);
      
      Polygon bridgepoly = new Polygon();
      for (int i = 0; i < points.length; i++)
         bridgepoly.addPoint((int)(points[i].getX() + 0.01),
               (int)(points[i].getY() + 0.01));
      
      path.append(bridgepoly, false);
      
      bufferRect = new Rectangle2D.Float(
            left - BUFFER, top - BUFFER,
            WIDTH + 2* BUFFER, HEIGHT + 2*BUFFER);
   }
}
